package shapes.shapes2D.curves 
{
	// forked from makc3d's A circle through three points (trail version)
	// forked from makc3d's A circle through three points

    import flash.display.*;
	import flash.display.Graphics;
    import flash.geom.*;
     
    /** 
    * Catmull-Rom spline through N points.
    * @author makc
    * @license WTFPLv2, http://sam.zoy.org/wtfpl/
    */ 
    public class CatmullRom 
    {
        public function CatmullRom (){}
		
        static public function compute( ps:Vector.<Point>, loop:Boolean = false, graphics:Graphics = null ):Vector.<Point>
		{
			var i:int, e:int;
			var q:Point, p0:Point, p1:Point, p2:Point, p3:Point;
			
            var tmp:Vector.<Point> = new Vector.<Point>();
			
			e = ps.length;
			
            // draw spline
            for (i = 0; i < e; i++) 
			{
				
				p0 = ps [(i -1 + ps.length) % ps.length];
				p1 = ps [i];
				p2 = ps [(i +1 + ps.length) % ps.length];
				p3 = ps [(i +2 + ps.length) % ps.length];
				
				
				tmp.push( p1 );
				
				if ( graphics )
				{
					graphics.moveTo (p1.x, p1.y);
				}
				
				for (var j:int = 1; j < 21; j++) 
				{
					q = spline (p0, p1, p2, p3, 0.05 * j);
					tmp.push( q )
					if( graphics ) graphics.lineTo (q.x, q.y);
				}
				
			}
			
			return tmp;
        }

        /* 
        * Calculates 2D cubic Catmull-Rom spline.
        * @see http://www.mvps.org/directx/articles/catmull/ 
        */ 
        static private function spline (p0:Point, p1:Point, p2:Point, p3:Point, t:Number):Point 
        {
            return new Point (
				0.5 * ((          2*p1.x) +
					t * (( -p0.x           +p2.x) +
					t * ((2*p0.x -5*p1.x +4*p2.x -p3.x) +
					t * (  -p0.x +3 * p1.x -3 * p2.x +p3.x)))),
					
				0.5 * ((          2*p1.y) +
					t * (( -p0.y           +p2.y) +
					t * ((2*p0.y -5*p1.y +4*p2.y -p3.y) +
					t * (  -p0.y +3*p1.y -3*p2.y +p3.y))))
			);
        }

    }

}